package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Attribute;
import com.wzcl.app.dao.repository.AttributeRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.WZCL;
import com.wzcl.app.model.dto.AttributeDto;
import com.wzcl.app.service.AttributeService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

@Log4j2
@Service
public class AttributeServiceImpl implements AttributeService {

    @Autowired
    private AttributeRepository repository;

    @Override
    public Attribute addAttribute(AttributeDto attributeDto) {
        //重复校验
        Attribute attribute = null;
        Integer parentId = attributeDto.getParentId();
        String name = attributeDto.getName();
        if(parentId == null){
            attribute = repository.findParentByName(name);
        }else {
            attribute = repository.findByNameAndParentId(name,parentId);
        }
        //存在
        if(attribute != null){
            return attribute;
        }
        if(parentId != null){
            Attribute parent = getAndCheckById(parentId);
            if(WZCL.ATTRIBUTE_TYPE.VALUE.equals(parent.getType())){
                throw new BusinessException(CodeMsg.SYSTEM_ERR,"属性值下不能再添加属性或值");
            }
        }
        attribute = new Attribute();
        BeanUtils.copyProperties(attributeDto,attribute);
        return repository.save(attribute);
    }

    @Override
    public Attribute delAttributeById(Integer id) {
        Attribute attribute = getAndCheckById(id);
        log.info("Attribute:{} Physical deletion", JSON.toJSONString(attribute));
        repository.delete(attribute);
        return attribute;
    }

    @Override
    public Attribute updateAttribute(AttributeDto attributeDto) {
        Attribute attribute = getAndCheckById(attributeDto);
        attribute.setName(attributeDto.getName());
        attribute.setType(attributeDto.getType());
        return repository.save(attribute);
    }

    @Override
    public List<Attribute> getList(AttributeDto attributeDto) {
        return repository.findAll(getSpecification(attributeDto));
    }

    private Specification<Attribute> getSpecification(AttributeDto attributeDto) {
        return new Specification<Attribute>() {
            @Override
            public Predicate toPredicate(Root<Attribute> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (StringUtils.isNotBlank(attributeDto.getName())) {
                    predicates.add(criteriaBuilder.like(root.get("name"), attributeDto.getName() + "%"));
                }
                if (attributeDto.getParentId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("parentId"), attributeDto.getParentId()));
                } else {
                    predicates.add(criteriaBuilder.isNull(root.get("parentId")));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }

    @Override
    public Attribute getAndCheckById(Integer id) {
        if(id == null){
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL,"缺少规格属性Id");
        }
        Attribute attribute = repository.findById(id).orElse(null);
        if(attribute == null){
            throw new BusinessException(CodeMsg.ATTRIBUTE_NOT_EXIST);
        }
        return attribute;
    }
}
